home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Tools / Win95 Secrets / SETUP.Z / INTRCPT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  7.0 KB  |  214 lines

  1. //==================================
  2. // APISPY32 - Matt Pietrek 1995
  3. // FILE: INTRCPT.C
  4. //==================================
  5. #include <windows.h>
  6. #include <malloc.h>
  7. #include <string.h>
  8. #include <stdio.h>
  9. #pragma hdrstop
  10. #include "intrcpt.h"
  11. #include "intrcpt2.h"
  12. #include "log.h"
  13.  
  14. PAPIFunction BuildAPIStub(PSTR pszModule, PSTR pszFuncName, PBYTE params);
  15.  
  16. // MakePtr is a macro that allows you to easily add to values (including
  17. // pointers) together without dealing with C's pointer arithmetic.  It
  18. // essentially treats the last two parameters as DWORDs.  The first
  19. // parameter is used to typecast the result to the appropriate pointer type.
  20. #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
  21.  
  22. #define MAX_INTERCEPTED_APIS 2048
  23. unsigned InterceptedAPICount = 0;
  24. PAPIFunction InterceptedAPIArray[MAX_INTERCEPTED_APIS];
  25.  
  26. extern BOOL FChicago;
  27. extern FILE * PLogFile;
  28.  
  29. BOOL AddAPIFunction
  30. (
  31.     PSTR pszModule,     // exporting DLL name
  32.     PSTR pszFuncName,   // exported function name
  33.     PBYTE params        // opcode encoded parameters of exported function
  34. )
  35. {
  36.     PAPIFunction pNewFunction;
  37.  
  38.     if ( InterceptedAPICount >= MAX_INTERCEPTED_APIS )
  39.         return FALSE;
  40.     
  41.     pNewFunction = BuildAPIStub(pszModule, pszFuncName, params);
  42.     if ( !pNewFunction )
  43.         return FALSE;
  44.     
  45.     InterceptedAPIArray[ InterceptedAPICount++ ] = pNewFunction;
  46.     
  47.     return TRUE;
  48. }
  49.  
  50.  
  51. PAPIFunction BuildAPIStub(PSTR pszModule, PSTR pszFuncName, PBYTE params)
  52. {
  53.     UINT allocSize;
  54.     PAPIFunction pNewFunction;
  55.     PVOID realProcAddress;
  56.     UINT cbFuncName;
  57.     HMODULE hModule;
  58.     
  59.     hModule = GetModuleHandle(pszModule);
  60.     if ( !hModule )
  61.         return 0;
  62.     
  63.     realProcAddress = GetProcAddress( hModule, pszFuncName );
  64.     if ( !realProcAddress )
  65.         return 0;
  66.     
  67.     cbFuncName = strlen(pszFuncName);
  68.     allocSize = sizeof(APIFunction) + cbFuncName +1 + *params + 1;
  69.  
  70.     pNewFunction = malloc(allocSize);
  71.     if ( !pNewFunction )
  72.         return 0;
  73.  
  74.     pNewFunction->RealProcAddress = realProcAddress;
  75.     pNewFunction->instr_pushad = 0x60;
  76.     pNewFunction->instr_lea_eax_esp_plus_32 = 0x2024448D;
  77.     pNewFunction->instr_push_eax = 0x50;
  78.     pNewFunction->instr_push_offset_params = 0x68;
  79.     pNewFunction->offset_params = (DWORD)(pNewFunction + 1) + cbFuncName + 1;
  80.     pNewFunction->instr_push_offset_funcName = 0x68;
  81.     pNewFunction->offset_funcName = (DWORD)(pNewFunction + 1);
  82.     pNewFunction->instr_call_LogFunction = 0xE8;
  83.     pNewFunction->offset_LogFunction
  84.         =  (DWORD)LogCall - (DWORD)&pNewFunction->instr_popad;
  85.     pNewFunction->instr_popad = 0x61;
  86.     pNewFunction->instr_jmp_dword_ptr_RealProcAddress = 0x25FF;
  87.     pNewFunction->offset_dword_ptr_RealProcAddrss = (DWORD)pNewFunction;
  88.  
  89.     strcpy( (PSTR)pNewFunction->offset_funcName, pszFuncName );
  90.     memcpy( (PVOID)pNewFunction->offset_params, params, *params+1 );
  91.     
  92.     return pNewFunction;
  93. }
  94.  
  95.  
  96. PAPIFunction LookupInterceptedAPI( PVOID address )
  97. {
  98.     unsigned i;
  99.     PVOID stubAddress;
  100.     
  101.     for ( i=0; i < InterceptedAPICount; i++ )
  102.     {
  103.         if ( InterceptedAPIArray[i]->RealProcAddress == address )
  104.             return InterceptedAPIArray[i];
  105.     }
  106.  
  107.     // If it's Chicago, and the app is being debugged (as this app is)
  108.     // the loader doesn't fix up the calls to point directly at the
  109.     // DLL's entry point.  Instead, the address in the .idata section
  110.     // points to a PUSH xxxxxxxx / JMP yyyyyyyy stub.  The address in
  111.     // xxxxxxxx points to another stub: PUSH aaaaaaaa / JMP bbbbbbbb.
  112.     // The address in aaaaaaaa is the real address of the function in the
  113.     // DLL.  This ugly code verifies we're looking at this stub setup,
  114.     // and if so, grabs the real DLL entry point, and scans through
  115.     // the InterceptedAPIArray list of addresses again.
  116.     // ***WARNING*** ***WARNING*** ***WARNING*** ***WARNING*** 
  117.     // This code is subject to change, and is current only as of 9/94.
  118.  
  119.     if ( FChicago )
  120.     {
  121.         
  122.         if ( address < (PVOID)0x80000000 )  // Only shared, system DLLs
  123.             return 0;                       // have stubs
  124.         
  125.         if ( IsBadReadPtr(address, 9) || (*(PBYTE)address != 0x68)
  126.              || (*((PBYTE)address+5) != 0xE9) )
  127.             return 0;
  128.  
  129.         stubAddress = (PVOID) *(PDWORD)((PBYTE)address+1);
  130.  
  131.         for ( i=0; i < InterceptedAPICount; i++ )
  132.         {
  133.             PVOID lunacy;
  134.             
  135.             if ( InterceptedAPIArray[i]->RealProcAddress == stubAddress )
  136.                 return InterceptedAPIArray[i];
  137.             
  138.             lunacy = InterceptedAPIArray[i]->RealProcAddress;
  139.             
  140.             if ( !IsBadReadPtr(lunacy, 9) && (*(PBYTE)lunacy == 0x68)
  141.                 && (*((PBYTE)lunacy+5) == 0xE9) )
  142.             {
  143.                 lunacy = (PVOID)*(PDWORD)((PBYTE)lunacy+1);
  144.                 if ( lunacy == stubAddress )
  145.                     return InterceptedAPIArray[i];
  146.             }
  147.         }
  148.     }
  149.  
  150.     return 0;
  151. }
  152.  
  153. BOOL InterceptFunctionsInModule(PVOID baseAddress)
  154. {
  155.     PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)baseAddress;
  156.     PIMAGE_NT_HEADERS pNTHeader;
  157.     PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
  158.     
  159.     if ( IsBadReadPtr(baseAddress, sizeof(PIMAGE_NT_HEADERS)) )
  160.         return FALSE;
  161.     
  162.     if ( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
  163.         return FALSE;
  164.  
  165.     pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
  166.     if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
  167.         return FALSE;
  168.     
  169.     pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, baseAddress, 
  170.                             pNTHeader->OptionalHeader.
  171.                             DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
  172.                             VirtualAddress);
  173.                         
  174.     // Bail out if the RVA of the imports section is 0 (it doesn't exist)
  175.     if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader )
  176.         return FALSE;
  177.  
  178.     while ( pImportDesc->Name )
  179.     {
  180.         PIMAGE_THUNK_DATA pThunk;
  181.         
  182.         pThunk = MakePtr(PIMAGE_THUNK_DATA,
  183.                          baseAddress, pImportDesc->FirstThunk);
  184.  
  185.         while ( pThunk->u1.Function )
  186.         {
  187.             PAPIFunction pInterceptedFunction;
  188.             
  189.             pInterceptedFunction = LookupInterceptedAPI(pThunk->u1.Function);
  190.  
  191.             if ( pInterceptedFunction )
  192.             {
  193.                 DWORD cBytesMoved;
  194.                 DWORD src = (DWORD)&pInterceptedFunction->instr_pushad;
  195.                 
  196.                 // Bash the import thunk.  We have to use WriteProcessMemory,
  197.                 // since the import table may be in a code section (courtesy
  198.                 // of the NT 3.51 team!)
  199.                 
  200.                 WriteProcessMemory( GetCurrentProcess(),
  201.                                 &pThunk->u1.Function,
  202.                                 &src, sizeof(DWORD), &cBytesMoved );
  203.             }
  204.             
  205.             pThunk++;
  206.         }
  207.         
  208.         pImportDesc++;
  209.     }
  210.     
  211.     return TRUE;
  212. }
  213.  
  214.